package server;

import java.io.*;

/**
 * 读取class类并加载
 * 之所以使用自定义ClassLoader，是因为在不做特殊处理的情况下，任何类都是可以通过自定义的ClassLoader加载的，
 * 如果这个类之前已经被父ClassLoader加载过，内存中就会有多个具有相同全限定名的类被加载到内存中
 */
public class MyClassLoader extends ClassLoader {

    // 指定路径
    private String classPath;

    /**
     * 构造函数，参数为类路径，初始化类路径
     * @param classPath
     */
    public MyClassLoader(String classPath) {
        this.classPath = classPath;
    }

    /**
     * 重写findClass方法
     * 目的是为了保证加载的类符合双亲委派模型（如果使用loadClass方法没有实现双亲委派模型）
     *
     * @param name 是我们这个类的全路径
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    public Class<?> findClass(String name) {
        Class log = null;
        // 获取该class文件字节码数组
        byte[] classData = getData();

        if (classData != null) {
            // 将class的字节码数组转换成Class类的实例
            log = defineClass(name, classData, 0, classData.length);
        }
        return log;
    }

    /**
     * 将class文件转化为字节码数组
     *
     * @return
     */
    private byte[] getData() {
        File file = new File(classPath);
        if (file.exists()) {
            FileInputStream in = null;
            ByteArrayOutputStream out = null;
            try {
                in = new FileInputStream(file);
                out = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024];
                int size = 0;
                while ((size = in.read(buffer)) != -1) {
                    out.write(buffer, 0, size);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return out.toByteArray();
        } else {
            return null;
        }
    }
}
